#include "resources.h"

#include "gameboard.h"
#include "player.h"
#include "block.h"
#include "floor.h"
#include "box.h"
#include "wall.h"
#include "target.h"
#include "empty.h"
#include "exceptions.h"


bool Resources::_instanceFlag = 0;
Resources* Resources::_instance = NULL;


//Private
void Resources::load(){
    try{
        loadImages();
        loadMaps();
        loadFonts();
    }
    catch(Exceptions::ImageNotLoad e){
        std::cout << "Load Image Error:"<< e.msg;
    }
    catch(Exceptions::MapNotLoad e){
        std::cout << "Map Load Error"<< e.msg;
    }
    catch(Exceptions::FontNotLoad e){
        std::cout << "Font Load Error" << e.msg;
    }

}

void Resources::loadImages(){
    _images.push_back( loadImage("floor.jpg") );
    _images.push_back( loadImage("box.jpg") );
    _images.push_back( loadImage("box_ok.jpg") );
    _images.push_back( loadImage("wall.jpg") );
    _images.push_back( loadImage("target.png") );
    _images.push_back( loadImage("empty.gif") );
    _images.push_back( loadImage("player_u.gif") );
    _images.push_back( loadImage("player_r.gif") );
    _images.push_back( loadImage("player_d.gif") );
    _images.push_back( loadImage("player_l.gif") );
    _images.push_back( loadImage("p_nada.gif") );
    _images.push_back( loadImage("p_norte.gif") );
    _images.push_back( loadImage("p_sul.gif") );
    _images.push_back( loadImage("p_metal.gif") );
    _images.push_back( loadImage("bg.gif") );
    _images.push_back( loadImage("toolbox.png"));
}

void Resources::loadFonts(){
    _fonts.push_back( loadFont("super_mario_bros.ttf",20) );
}

void Resources::loadMaps(){
	util::FileReader f(mapsFile);

	int n,w,h,px,py;    /*#maps,width,height,player_x,player_y*/
	int i,j,pos;
	char c;

	char tipo;
	int dir[4];

	f.move( sscanf(f.stream(),"%d",&n) );
	_num_stages = n;
	f.moveUntilN();
	while(n>0){
		f.move( sscanf(f.stream(),"%d %d %d %d",&w,&h,&px,&py) );
		f.moveUntilN();

		matrixBlock map;
		std::vector< std::pair<int,int> > target_indexes;
		Block* nb;

		for(i=0;i<h;i++){
			rowBlock row;

			for(j=0;j<w*5;j++){
				pos = j%5;

				c = f.getChar();

				if( pos==0 ){
				    tipo = c;
				}else{
					dir[pos-1] = c;
				}

                if( pos==4 ){
                    if(tipo==TYPE_TILE_FLOOR){
                        nb = new Floor();
                    }else if(tipo==TYPE_TILE_EMPTY){
                        nb = new Empty();
                    }else if(tipo==TYPE_TILE_BLOCK){
                        nb = new Box( dir[0],dir[1],dir[2],dir[3] );
                    }else if(tipo==TYPE_TILE_WALL){
                            nb = new Wall(dir[0],dir[1],dir[2],dir[3] );
                    }else if(tipo==TYPE_TILE_TARGET){
                        nb = new Target();

                        std::pair<int,int> index;
                        index.first = map.size();
                        index.second = row.size();

                        target_indexes.push_back( index );
                    }else{
                        std::cout << "corrompido" << tipo;
                        f.close();
                        char mapNumber[16];
                        itoa(i,mapNumber,10);
                        throw Exceptions::MapNotLoad("Map File is corrupted. Error on Map Number: " + std::string(mapNumber));
                    }

                    row.push_back(nb);
                }

			}

			map.push_back(row);
			f.moveUntilN();
		}

		Player* p = new Player(px,py);
        _boards.push_back( new GameBoard(p,map,target_indexes) );

		n--;
	}
	f.close();
}

ALLEGRO_FONT* Resources::loadFont(std::string fontName,int size){
    ALLEGRO_FONT *font = al_load_ttf_font(fontName.c_str(),size,0 );

    if (!font){
        throw Exceptions::FontNotLoad(fontName);
    }

    return font;
}

ALLEGRO_BITMAP* Resources::loadImage(std::string name){
    std::string fullpath = std::string(FOLDER_IMAGES) + "/" + name;
    ALLEGRO_BITMAP* img;

    try{
        img = al_load_bitmap( fullpath.c_str() );
    }catch(Exceptions::ImageNotLoad){
        throw Exceptions::ImageNotLoad("Error loading image" + fullpath);
    }

    return img;
}

//Public
Resources* Resources::instance(){
	if(! _instanceFlag){
		_instance= new Resources();
		_instanceFlag = true;

		_instance->load();
		return _instance;
	}
	else{
		return _instance;
	}
}

void Resources::save_stage(int stage, GameBoard* gb){

    if( stage == (int) _boards.size()){
        _boards.push_back(gb);
    }else{
        _boards[stage] = gb;
    }

    writeMaps();

}

void Resources::writeMaps(){
    FILE* f;

    int type;
    int nboards = (int) _boards.size();

    char numbuffer[32];
    std::string save_string;
    matrixBlock mb;

    itoa(nboards,numbuffer,10);
    save_string += numbuffer;
    save_string += "\n";

    for(register int k=0;k<nboards;++k){
        std::cout << k << std::endl;
        mb = _boards[k]->_board;
        int rows = (int) mb.size();
        int cols = (int) mb[0].size();

        itoa(rows,numbuffer,10);
        save_string += numbuffer;
        save_string += " ";
        itoa(cols,numbuffer,10);
        save_string += numbuffer;
        save_string += " ";
        itoa(_boards[k]->playerRow(),numbuffer,10);
        save_string+=numbuffer;
        save_string += " ";
        itoa(_boards[k]->playerCol(),numbuffer,10);
        save_string+=numbuffer;
        save_string += "\n";

        for(register int i=0;i<rows;++i){
            for(register int j=0;j<cols;++j){
                save_string+= mb.at(i).at(j)->saveString();
            }
            save_string+="\n";
        }
    }

    f = fopen(mapsFile,"w");
    fwrite(save_string.c_str(),sizeof(char),(int) save_string.length(),f );
    fclose(f);
}
